﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Epsilon.Expr;

namespace Epsilon.Parse
{
    public partial class Parser
    {
        public void ParseAttribute()
        {
            Token t = CurrentToken();
            Match(TokenType.Symbol, "-");
            if (MatchPeek(TokenType.Keyword, "process"))
            {
                Chomp();
                Match(TokenType.Symbol, "(");
                if (CheckType(TokenType.Atom))
                {
                    p.Name = CurrentToken().Value;
                    Chomp();
                    Match(TokenType.Symbol, ")");
                }
                else
                {
                    Error("Expected a process name atom");
                }
            }
            else if (MatchPeek(TokenType.Keyword, "record"))
            {
                Chomp();
                Match(TokenType.Symbol, "(");
                if (CheckType(TokenType.Atom))
                {
                    string recName = CurrentToken().Value;
                    Chomp();
                    Match(TokenType.Symbol, ",");
                    Match(TokenType.Symbol, "{");
                    List<RecordField> fields = ParseRecordFields();
                    Match(TokenType.Symbol, "}");
                    Match(TokenType.Symbol, ")");
                    List<Tuple<string, Expression>> recFields = new List<Tuple<string, Expression>>();
                    foreach (RecordField f in fields)
                        recFields.Add(new Tuple<string, Expression>(f.Name.Value, f.Contents));
                    p.Records.AddRecordDef(new RecordDef(recName, recFields));
                }
                else
                {
                    Error("Expected a record name atom");
                }
            }
            else if (MatchPeek(TokenType.Keyword, "spec"))
            {
                Chomp();
                Match(TokenType.Symbol, "(");
                if (CheckType(TokenType.Atom))
                {
                    string name = CurrentToken().Value;
                    Chomp();
                    Match(TokenType.Symbol, ":");
                    if (CheckType(TokenType.Atom))
                    {
                        name += ":" + CurrentToken().Value;
                        Chomp();
                        Match(TokenType.Symbol, ",");
                        Type type = ParseType();
                        Match(TokenType.Symbol, ",");
                        PidLabel pmax = ParsePidLabel();
                        Match(TokenType.Symbol, ",");
                        PidLabel pmin = ParsePidLabel();
                        Match(TokenType.Symbol, ",");
                        SecLabel sec = ParseSecLabel();
                        Match(TokenType.Symbol, ")");
                        p.Specs.Add(name, new Typing.TypeLabel(type, pmax, pmin, sec));
                    }
                    else
                    {
                        Error("Expected a function name");
                    }
                }
                else
                {
                    Error("Expected a module name");
                }
            }
            else if (CheckType(TokenType.Atom))
            {
                string name = CurrentToken().Value;
                Chomp();
                Match(TokenType.Symbol, "(");
                List<Expression> exprs = ParseArgExprs();
                Match(TokenType.Symbol, ")");
                p.Attributes.Add(new AttributeExpr(name, exprs, t.Line, t.Col));
            }
            else
            {
                Error("Expected an attribute name");
            }
        }
    }
}
